#include "BlockQueue.hpp"
#include "Task.hpp"
#include <pthread.h>
#include <unistd.h>
#include <ctime>
int myAdd(int x, int y)
{
    return x + y;
}
// 生产者消费者模型提高效率，消费线程和生产线程处理数据都需要时间的，但是生产者可以一直往仓库里放数据，消费者可以一直从仓库里拿数据，两个线程就实现了一定的并发
// 所以生产者消费者模型提高效率，更多的是利用缓冲区，提高消费线程和生产线程的并发度，并发不是拿任务时并发，而是处理任务时并发

void *consumer(void *args)
{
    BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;
    while (true)
    {
        // 获取任务
        Task t;
        bqueue->pop(&t);
        // std::cout << "消费一个数据：" << a << std::endl;
        // 完成任务
        std::cout << pthread_self() << " consumer: " << t._x << " + " << t._y << " = " << t() << std::endl;
        sleep(1);
    }
    return nullptr;
}

void *productor(void *args)
{
    BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;
    while (true)
    {
        // 制作任务 --> 以后这个任务可能从各种途径来
        int x = rand() % 10 + 1;
        usleep(rand() % 1000);
        int y = rand() % 5 + 1;
        Task t(x, y, myAdd); // 制作一个简单的加法任务
        // 生产任务
        bqueue->push(t);
        // std::cout << "生产一个数据：" << a << std::endl;
        // a++;
        std::cout << pthread_self() << " productor: " << t._x << " + " << t._y << " = ?" << std::endl;

        sleep(1);
    }
    return nullptr;
}

int main() // 负责生产消费
{
    srand((uint64_t)time(nullptr) ^ getpid() ^ 0x32457);
    BlockQueue<Task> *bqueue = new BlockQueue<Task>();

    pthread_t c[2], p[2];
    pthread_create(c, nullptr, consumer, bqueue); // 线程传参是可以传递对象的
    pthread_create(c + 1, nullptr, consumer, bqueue);

    pthread_create(p, nullptr, productor, bqueue);
    pthread_create(p + 1, nullptr, productor, bqueue);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    delete bqueue;
    return 0;
}